/* ===================

AX2E (AXESCON XACML 2.0 Engine) is the Java authorization engine, which implements OASIS XACML 2.0 standard.
Copyright (C) 2007 AXESCON LLC

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


Contact: AXESCON LLC - info{at}axescon.com

 =================== */
package axescon.xacml.samples;

import axescon.xacml.api.*;
import axescon.xacml.util.EngineConfigurator;
import axescon.xacml.xb.ctx.XBAttrValueFactoryManager;
import axescon.xacml.xb.ctx.XBPolicyFactory;
import axescon.xacml.xb.ctx.XBRequestFactory;
import axescon.xacml.xb.ctx.XBResponseFactory;
import axescon.xacml.xb.engine.XBAttributeSelectorEvaluator;

import java.util.Properties;
import java.util.logging.Logger;

/**
 * @author argyn
 *         Date: Oct 24, 2005
 *         Responsibilities:
 *         read properties file, instantiate PDP components, cache them in instance
 *         variables
 *         this will be the basic configurator, more advanced one is to be Spring based
 */
public class BasicConfigurator implements EngineConfigurator {

    static Logger log = Logger.getLogger("axescon.xacml.samples.BasicConfigurator");

    public static final String REQUEST_FACTORY_CLASS_NAME = "factory.request.class.name";
    public static final String REQUEST_FACTORY_DEFAULTS = "factory.request.defaults";

    public static final String RESPONSE_FACTORY_CLASS_NAME = "factory.response.class.name";
    public static final String RESPONSE_FACTORY_DEFAULTS = "factory.response.defaults";

    public static final String POLICY_FACTORY_CLASS_NAME = "factory.policy.class.name";
    public static final String POLICY_FACTORY_DEFAULTS = "factory.policy.defaults";

    public static final String ATTRIBUTE_SELECTOR_EVALUATOR_CLASS_NAME = "attribute.selector.evaluator.class.name";
    public static final String ATTRIBUTE_SELECTOR_EVALUATOR_DEFAULTS = "attribute.selector.evaluator.defaults";

    public static final String POLICY_EVALUATOR_CLASS_NAME = "policy.evaluator.class.name";
    public static final String POLICY_EVALUATOR_DEFAULTS = "policy.evaluator.defaults";


    private ResponseFactory responseFactory;
    private XBRequestFactory requestFactory;


    public ResponseFactory getResponseFactory() {
        return responseFactory;
    }


    public RequestFactory getRequestFactory() {
        return requestFactory;
    }

    public PolicyFactory getPolicyFactory() {
        return policyFactory;
    }

    private XBPolicyFactory policyFactory;
    PolicyEvaluator policyEvaluator;


    public PolicyEvaluator getPolicyEvaluator() {
        return policyEvaluator;
    }


    /**
     * constructs this configurator from properties file
     *
     * @param props
     * @throws XacmlException
     */
    public BasicConfigurator(Properties props) throws XacmlException {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();

        requestFactory = new XBRequestFactory(true);
        XBAttrValueFactoryManager avfm =  requestFactory.getXbAttrValueFactoryManager();

        String cn = props.getProperty(RESPONSE_FACTORY_CLASS_NAME);
        responseFactory = (ResponseFactory) loadClass(cl, cn);
        if (getBoolean(props, RESPONSE_FACTORY_DEFAULTS, true))
            responseFactory.setDefaults();

        XBAttributeSelectorEvaluator ase = new XBAttributeSelectorEvaluator(false);
         ase.setXbAttrValueFactoryManager(avfm);

        cn = props.getProperty(POLICY_EVALUATOR_CLASS_NAME);
        policyEvaluator = (PolicyEvaluator) loadClass(cl, cn);
        if (getBoolean(props, POLICY_EVALUATOR_DEFAULTS, true))
            policyEvaluator.setDefaults();
        policyEvaluator.getTargetMatcher().getExpressionEvaluator().setAttributeSelectorEvaluator(ase);

        policyFactory = new XBPolicyFactory();
        policyFactory.setXbAttrValueFactoryManager(avfm);
        policyFactory.getXbPolicyTargetFactory().setXbAttrValueFactoryManager(avfm);

    }

    /**
     * gets boolean value from properties file
     *
     * @param props        properties
     * @param name         property name
     * @param defaultValue used , if property value is missing
     * @return boolean property value
     */
    boolean getBoolean(Properties props, String name, boolean defaultValue) {
        String val = props.getProperty(name, "" + defaultValue);
        return Boolean.valueOf(val).booleanValue();
    }


    /**
     * loads class instance by its name, using default constructor
     *
     * @param cl        class loader
     * @param className class name
     * @return instance of class
     * @throws XacmlException
     */
    Object loadClass(ClassLoader cl, String className) throws XacmlException {
        try {
            Class clazz = cl.loadClass(className);
            return (clazz).newInstance();
        } catch (Exception x) {
            throw new XacmlException("BasicConfigurator cant load class: " + className, x
                    , XacmlException.ERR_CODE_CLASS_LOAD);
        }

    }


}
